package images_api

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"gvb_server/global"
	"gvb_server/models"
	"gvb_server/models/ctype"
	"gvb_server/models/res"
	"gvb_server/utils"
	"io"
	"mime/multipart"
	"path"
	"strings"
)

var (
	WhiteImageList = []string{
		".jpg",
		".jpeg",
		".png",
		".gif",
		".bmp",
		".webp",
		".tiff",
		".psd",
		".ai",
		".eps",
		".raw",
		".cr2",
		".nef",
		".orf",
		".arw",
		".srw",
		".arw",
	}
)

type FileUploadResponse struct {
	FileName  string `json:"file_name"`
	IsSuccess bool   `json:"is_success"`
	Msg       string `json:"msg"`
}

// ImageUpload 上传单个图片
func (imagesApi ImagesApi) ImageUpload(c *gin.Context) {
	form, err := c.MultipartForm()
	if err != nil {
		return
	}
	fileList, ok := form.File["images"]
	if !ok {
		return
	}
	var resList []FileUploadResponse
	for _, file := range fileList {
		fileName := file.Filename
		var msg string
		// 1.校验文件
		hash := verifyFile(file, &msg)
		if msg != "" {
			resList = append(resList, FileUploadResponse{
				FileName:  fileName,
				IsSuccess: false,
				Msg:       msg,
			})
			continue
		}
		// 2.上传文件
		filePath, err := uploadFile(file)
		if err != nil {
			resList = append(resList, FileUploadResponse{
				FileName:  fileName,
				IsSuccess: false,
				Msg:       "上传失败",
			})
			continue
		}
		// 3.保存信息到数据库
		saveFileInfo(fileName, filePath, hash)
		resList = append(resList, FileUploadResponse{
			FileName:  filePath,
			IsSuccess: true,
			Msg:       "上传成功",
		})
	}
	res.OkWithData(resList, c)
}

func verifyFile(file *multipart.FileHeader, msg *string) string {
	fileSize := float64(file.Size / (1024 * 1024))
	fileName := file.Filename
	var fileDataHash string
	// 判断文件后缀是否符合要求
	if !utils.StringInSlice(strings.ToLower(path.Ext(fileName)), WhiteImageList) {
		*msg = fmt.Sprintf("上传失败, 文件名后缀: %s不在%v里", path.Ext(fileName), WhiteImageList)
		// 判断文件的大小
	} else if fileSize > global.Config.Local.Size {
		*msg = fmt.Sprintf("上传失败, 上传文件大小不能超过%.2fMB, 当前大小为: %.2fMB", global.Config.Local.Size, fileSize)
	} else {
		// 判断文件是否在数据库中存在，计算hash值
		openFile, err := file.Open()
		if err != nil {
			global.Log.Errorf("open file error: %s", err)
			*msg = "打开文件出错"
		}
		byteData, err := io.ReadAll(openFile)
		if err != nil {
			global.Log.Errorf("read file error: %s", err)
			*msg = "读取文件出错"
		}
		fileDataHash = utils.Md5(byteData)
		// 去数据库中查找当前hash值是否存在
		affected := global.DB.Take(&models.BannerModel{}, "hash = ?", fileDataHash).RowsAffected
		if affected > 0 {
			*msg = "缓存文件"
		}
	}
	if *msg != "" {
		return ""
	}
	return fileDataHash
}

func uploadFile(file *multipart.FileHeader) (filePath string, err error) {
	// 根据策略上传文件
	filePath, err = utils.Upload(file)
	if err != nil {
		global.Log.Errorf("upload file error: %s", err)
		return "", err
	}
	return filePath, nil
}

func saveFileInfo(fileName, filePath, fileDataHash string) {
	// 保存文件信息到数据库
	global.DB.Create(&models.BannerModel{
		Name:      fileName,
		Path:      filePath,
		Hash:      fileDataHash,
		ImageType: ctype.GetImageType(global.Config.System.Storage),
	})
}
